Umsetzung ========= Reverse-Proxy über Traefik -------------------------- Docker Compose Definition ````````````````````````` Wir verwenden wieder Traefik, um die GUIs von Prometheus und Grafana über die Domains ``prom.dva.mahart.ma`` und ``grafana.dva.mahart.ma`` per https zu erreichen. Wir haben bereits Erfahrung mit dem Reverse Proxy und können daher eine angepasste Docker Compose Definition aus dem letzten Versuch wiederverwenden. .. code-block:: yaml networks: grafana: external: true services: watchtower: image: containrrr/watchtower container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock command: --label-enable --interval=43200 --cleanup networks: - grafana traefik: image: "traefik:v2.11" container_name: "traefik" command: #- "--log.level=DEBUG" #- "--api.insecure=true" - "--api.dashboard=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=web" - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - "--entrypoints.websecure.address=:443" - "--entrypoints.websecure.http.middlewares=https_config@docker,www-redirect@docker" - "--entrypoints.websecure.http.tls.options=default" - "--entrypoints.websecure.http.tls.certresolver=myresolver" - "--certificatesresolvers.myresolver.acme.tlschallenge=true" #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" - "--certificatesresolvers.myresolver.acme.email=mahartma@mahartma.com" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" labels: traefik.enable: true # https redirect traefik.http.middlewares.https_config.redirectscheme.scheme: "https" traefik.http.middlewares.https_config.redirectscheme.permanent: true # www -> non-www traefik.http.middlewares.www-redirect.redirectregex.regex: "^https://www.(.*)" traefik.http.middlewares.www-redirect.redirectregex.replacement: "https://$${1}" traefik.http.middlewares.www-redirect.redirectregex.permanent: true # basic-auth # Note: when used in docker-compose.yml all dollar signs in the hash need to be doubled for escaping. # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g traefik.http.middlewares.dev-auth.basicauth.users: "dva:$$apr1$$gUBBy11O$$w.owgrn.62lbLkM2ON.1p0" # password: secure # dashboard traefik.http.routers.api.rule: Host(`traefik.dva.mahart.ma`) traefik.http.routers.api.service: api@internal traefik.http.routers.api.middlewares: dev-auth traefik.http.routers.api.entrypoints: websecure # auto updates via watchtower com.centurylinklabs.watchtower.enable: true ports: - "443:443" - "80:80" volumes: - "/var/lib/traefik/letsencrypt:/letsencrypt" - "/var/run/docker.sock:/var/run/docker.sock:ro" networks: - grafana - default restart: unless-stopped Prometheus und Grafana Services werden im gleichen Netzwerk wie Traefik betrieben, um die Kommunikation zu gewährleisten. Da die Prometheus GUI keine Authentifizierung hat, haben wir Basic-Auth eingerichtet. Auch die automatische Provisionierung von Zertifikaten über Let's Encrypt kann für Services einfach aktiviert werden. Beides kann für die jeweiligen Services über Labels aktiviert werden. Das Traefik Dashboard ist über die Domain ``traefik.dva.mahart.ma`` erreichbar. Watchtower ist ebenfalls für alle Services aktiviert, um automatische Updates zu gewährleisten. Quellen: - https://doc.traefik.io/traefik/providers/docker/ - https://doc.traefik.io/traefik/middlewares/http/basicauth/ - https://doc.traefik.io/traefik/middlewares/http/redirectscheme/ - https://doc.traefik.io/traefik/middlewares/http/redirectregex/ - https://doc.traefik.io/traefik/https/acme/ Prometheus ---------- Docker Compose Definition ````````````````````````` Auch die Prometheus-Instanz wurde mithilfe von Docker Compose aufgesetzt. .. code-block:: yaml services: prometheus: image: docker.io/prom/prometheus:latest container_name: prometheus user: root ports: - 9090:9090 networks: - grafana command: "--config.file=/etc/prometheus/prometheus.yaml" volumes: - ./prometheus/prometheus.yaml:/etc/prometheus/prometheus.yaml:ro - ./prometheus/prometheus-data:/prometheus depends_on: - cadvisor - node_exporter restart: unless-stopped labels: - traefik.enable=true - "traefik.http.routers.prom.rule=Host(`prom.dva.mahart.ma`)" - "traefik.http.routers.prom.entrypoints=websecure" - "traefik.http.routers.prom.tls.certresolver=myresolver" - "traefik.http.routers.prom.service=prom-prom" - "traefik.http.services.prom-prom.loadbalancer.server.port=9090" - "traefik.http.routers.prom.middlewares=dev-auth" # enable basic auth - "com.centurylinklabs.watchtower.enable=true" In dieser Service-Definition binden wir direkt das offzielle Image von prometheus ein. Port und Network werden definiert, um die kommunikation zwischen den Instanzen zu gewährleisten und die Weboberfläche zugänglich machen zu können. Im ``command:`` referenzieren wir auf die zu verwendende config, welche wir unter ``volumes:`` als Read-Only in den Container mounten. Des Weiteren wird noch ein zusätzliches Verzeichnis in den Container gemounted um die Daten über den Lebenszyklus des Containers hinweg persistent zu halten. Abschließend werden wieder Traefik Labels gesetzt, um die Kommunikation über den Reverse Proxy, die automatische Zertifikatsverwaltung und Basic-Auth zu aktivieren. Die grafische Oberfläche von Prometheus ist über die Domain ``prom.dva.mahart.ma`` erreichbar. Sie kann verwendet werden, um die Datenquellen und Jobs zu überwachen. Quellen: - https://prometheus.io/docs/prometheus/latest/installation/ Prometheus Konfiguration ```````````````````````` Die Prometheus-config wird ebenfalls im YAML-format definiert. Die Config wurde in der Docker-Compose Definition über einen Bind-Mount in den Container gemounted und wird beim Start des Containers eingelesen, um die Jobs entsprechend zu starten. Versionsverwaltung und Backup der Config sind daher sehr wichtig. .. code-block:: yaml global: scrape_interval: 15s scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090'] Nebst den globalen Settings wie z.B. das ``scrape_intervall``, können hier die worker-jobs definiert werden. Mit den Jobs konfigurieren wir, welche Services an welcher Adresse und in welchem Intervall gescraped werden sollen. Wir haben hier zu Beginn nur einen Job, welcher den Prometheus-Server selbst überwacht. Im späteren Verlauf können hier weitere Jobs hinzugefügt werden, in unserem Beispiel der ``cadvisor`` und der ``node_exporter``. Quellen: - https://prometheus.io/docs/prometheus/latest/getting_started/ Exporter ```````` Wir haben zwei Exporter hinzugefügt, um Metriken über die Systemressourcen des Host-Systems und die darauf laufenden Docker-Container zu sammeln. Die Prometheus-Instanz schreibt seine eigenen Metriken auch in die Datenbank, braucht dafür also keinen eigenen Exporter. Node Exporter ^^^^^^^^^^^^^ Node Exporter ist ein Exporter für die Metriken des Betriebssystems. Er sammelt Metriken wie CPU-Auslastung, Speicher, Festplattenplatz und Netzwerkstatistiken. Die Metriken werden dann von Prometheus gescraped und können später in Grafana visualisiert werden. Der Node-Exporter wird unter der Apache 2.0 Lizenz bei Prometheus entwickelt und ist in Golang geschrieben. Das Deployment des Node-Exporters erfolgt über folgende Docker-Compose Definition: .. code-block:: yaml node_exporter: image: quay.io/prometheus/node-exporter:latest container_name: node_exporter command: - '--path.rootfs=/host' network_mode: host pid: host restart: unless-stopped volumes: - '/:/host:ro,rslave' labels: - "com.centurylinklabs.watchtower.enable=true" Der Prometheus-Config wird eine weitere ``scrape_config`` hinzugefügt, um die Metriken des Node-Exporters zu sammeln: .. code-block:: yaml # job for node_exporter - job_name: 'node_exporter' static_configs: - targets: ['node_exporter:9100'] Quellen: - https://github.com/prometheus/node_exporter - https://prometheus.io/docs/guides/node-exporter cAdvisor ^^^^^^^^ CAdvisor ist ein Container-Advisor, der Metriken über die Containerleistung und die aktuell laufenden Container sammelt. Das Tool wird unter der Apache 2.0 Lizenz bei Google entwickelt, ebenfalls in Golang. Auch der cAdvisor wird über Docker-Compose deployt: .. code-block:: yaml cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor ports: - 8080:8080 volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro depends_on: - redis networks: - grafana restart: unless-stopped labels: - "com.centurylinklabs.watchtower.enable=true" redis: image: redis:latest container_name: redis ports: - 6379:6379 networks: - grafana restart: unless-stopped labels: - "com.centurylinklabs.watchtower.enable=true" Der cAdvisor stützt sich auf die Docker API, um Metriken über die Containerleistung zu sammeln. Die Metriken werden dann von Prometheus gescraped und können in Grafana visualisiert werden. Der Prometheus-Config wird eine weitere ``scrape_config`` hinzugefügt, um die Metriken des cAdvisors zu sammeln: .. code-block:: yaml # job for cadvisor - job_name: 'cadvisor' static_configs: - targets: ['cadvisor:8080'] Quellen: - https://github.com/google/cadvisor - https://prometheus.io/docs/guides/cadvisor/ - https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md Grafana ------- Docker Compose Definition ````````````````````````` Wir verwenden das offizielle Grafana Docker Image, um unsere Grafana Instanz über Docker Compose zu betreiben. Die Konfiguration erfolgt über Umgebungsvariablen. .. code-block:: yaml networks: grafana: external: true services: grafana: image: grafana/grafana-enterprise container_name: grafana restart: unless-stopped environment: - GRAFANA_VERSION=latest - GF_INSTALL_IMAGE_RENDERER_PLUGIN=true - GF_SERVER_ROOT_URL=https://grafana.dva.mahart.ma - GF_INSTALL_PLUGINS=grafana-clock-panel - GF_USERS_ALLOW_SIGN_UP=true networks: - grafana ports: - '127.0.0.1:3000:3000' volumes: - grafana-data:/var/lib/grafana labels: - traefik.enable=true - "traefik.http.routers.grafana.rule=Host(`grafana.dva.mahart.ma`)" - "traefik.http.routers.grafana.entrypoints=websecure" - "traefik.http.routers.grafana.tls.certresolver=myresolver" - "traefik.http.routers.grafana.service=grafana-grafana" - "traefik.http.services.grafana-grafana.loadbalancer.server.port=3000" - "traefik.http.routers.grafana.middlewares=dev-auth" # enable basic auth - "com.centurylinklabs.watchtower.enable=true" volumes: grafana-data: {} Unsere Grafana Instanz nimmt Anfragen auf dem **lokalen** Port 3000 im externen Netzwerk ``grafana`` entgegen. Traefik wurde über die Labels konfiguriert, um die Kommunikation über den Reverse Proxy zu ermöglichen. Die Labels setzen die Domain auf ``grafana.dva.mahart.ma`` und aktivieren Basic-Auth. Die automatische Zertifikatsverwaltung über Let's Encrypt ist ebenfalls aktiviert. Ein Volume namens ``grafana-data`` wird über einen Bind-Mount angebunden, um Daten über den Lebenszyklus des Containers hinweg persistent zu halten. Die grafische Oberfläche von Grafana ist über die Domain ``grafana.dva.mahart.ma`` erreichbar. Sie kann verwendet werden, um Dashboards zu erstellen und zu verwalten, Datenquellen zu konfigurieren und Benutzer zu verwalten. Quellen: - https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/ Prometheus als Datenquelle hinzufügen ````````````````````````````````````` Das Hinzufügen von Datenquellen ist ein simpler Schritt, der in der Weboberfläche von Grafana durchgeführt werden kann. Wir haben Prometheus als Datenquelle hinzugefügt, um die Daten aus Prometheus in Grafana zu visualisieren. Beim Anlegen der Datenquelle müssen wir die URL von Prometheus angeben, die in unserem Fall ``http://localhost:9090`` ist. Beim Anlegen von Dashboards können wir dann die Datenquelle auswählen, um die Daten aus Prometheus zu visualisieren. Quellen: - https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/ Dashboards anlegen `````````````````` Dashboards können in Grafana über die Weboberfläche erstellt und angepasst werden. Es gibt auch die Möglichkeit, Dashboards als JSON-Dateien zu exportieren und zu importieren. Über den Grafana Marketplace können vorgefertigte Dashboards heruntergeladen und importiert werden bzw. über die ID des Dashboards direkt importiert werden. Hier ist natürlich zu beachten, dass die Datenquellen korrekt konfiguriert sind, um die Daten aus Prometheus zu visualisieren. Node-Exporter Dashboard ^^^^^^^^^^^^^^^^^^^^^^^ Wir verwenden ein vorgefertigtes Dashboard für den Node-Exporter, um einen Überblick über die Systemressourcen zu erhalten. Das Dashboard wurde über die ID ``1860`` importiert. Das Dashboard stützt sich auf die Daten aus Prometheus, die von der Node-Exporter-Instanz gescraped werden. Quellen: - https://grafana.com/grafana/dashboards/1860-node-exporter-full/ Docker Dashboard ^^^^^^^^^^^^^^^^ Wir verwenden ein vorgefertigtes Dashboard für Docker, um einen Überblick über die Container und Hosts zu erhalten. Das Dashboard wurde über die ID ``10619`` importiert. Das Dashboard stützt sich auf die Daten aus Prometheus, die von der cAdvisor-Instanz gescraped werden. Quellen: - https://grafana.com/grafana/dashboards/10619-docker-host-container-overview/ Google OAuth Konfiguration `````````````````````````` **Schritt 1: Erstellung eines Google OAuth-Client-IDs** 1. Die Google API-Konsole wird unter https://console.developers.google.com/apis/credentials aufgerufen. 2. `Credentials erstellen` wird ausgewählt, dann `OAuth-Client-ID` aus dem Dropdown-Menü. 3. Folgende Informationen werden eingegeben: - Anwendungstyp: Webanwendung - Name: Grafana - Autorisierte JavaScript-Ursprünge: `https://grafana.dva.mahart.ma` - Autorisierte Weiterleitungs-URLs: `https://grafana.dva.mahart.ma/login/google` **Schritt 2: Hinzufügen von Umgebungsvariablen in Docker Compose** .. code-block:: yaml environment: - GF_AUTH_GOOGLE_ENABLED=true - GF_AUTH_GOOGLE_ALLOW_SIGN_UP=true - GF_AUTH_GOOGLE_AUTO_LOGIN=false - GF_AUTH_GOOGLE_CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - GF_AUTH_GOOGLE_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - GF_AUTH_GOOGLE_AUTH_URL=https://accounts.google.com/o/oauth2/v2/auth - GF_AUTH_GOOGLE_TOKEN_URL=https://oauth2.googleapis.com/token - GF_AUTH_GOOGLE_API_URL=https://openidconnect.googleapis.com/v1/userinfo - GF_AUTH_GOOGLE_HOSTED_DOMAIN=dva.mahart.ma - GF_AUTH_GOOGLE_USE_PKCE=true - GF_AUTH_GOOGLE_SCOPES=openid email profile - `GF_AUTH_GOOGLE_ENABLED`: Aktiviert die Google Authentifizierung. - `GF_AUTH_GOOGLE_ALLOW_SIGN_UP`: Ermöglicht neuen Benutzern die Anmeldung via Google, wenn sie noch keinen Account haben. - `GF_AUTH_GOOGLE_AUTO_LOGIN`: Steuert, ob Benutzer automatisch eingeloggt werden, nachdem sie sich authentifiziert haben. - `GF_AUTH_GOOGLE_CLIENT_ID und GF_AUTH_GOOGLE_CLIENT_SECRET`: Diese Schlüssel identifizieren Ihre Grafana-Instanz sicher gegenüber Google und sind essentiell für die Authentifizierung. - `GF_AUTH_GOOGLE_AUTH_URL, GF_AUTH_GOOGLE_TOKEN_URL, GF_AUTH_GOOGLE_API_URL`: URLs, die für den Authentifizierungsprozess mit Google verwendet werden. - `GF_AUTH_GOOGLE_HOSTED_DOMAIN`: Beschränkt die Anmeldung auf Nutzer aus einer spezifischen Google Domain. - `GF_AUTH_GOOGLE_USE_PKCE`: Verbessert die Sicherheit während des Authentifizierungsprozesses durch Verwendung des PKCE-Verfahrens (Proof Key for Code Exchange). - `GF_AUTH_GOOGLE_SCOPES`: Definiert die Bereiche, auf die Grafana Zugriff haben wird, wenn es mit Google kommuniziert (z.B. Profilinformationen des Benutzers). **Vorteile der Google OAuth-Authentifizierung** - **Sicherheit**: Die Authentifizierung erfolgt über Google, was bedeutet, dass die Sicherheit der Anmeldedaten in den Händen von Google liegt. - **Benutzerfreundlichkeit**: Benutzer können sich mit ihren Google-Anmeldeinformationen anmelden, was den Anmeldevorgang vereinfacht. - **Verwaltung**: Administratoren können die Anmeldung über Google steuern, z.B. durch Beschränkung auf bestimmte Domains. - **Single Sign-On (SSO)**: Benutzer können sich bei mehreren Diensten anmelden, die Google OAuth verwenden, ohne sich jedes Mal erneut anmelden zu müssen. - **Skalierbarkeit und Flexibilität**: Google OAuth skaliert nahtlos mit der Anzahl der Nutzer und unterstützt komplexe Berechtigungsszenarien, die sich leicht an die wachsenden Bedürfnisse einer Organisation anpassen lassen.